package com.lcifn.middleware.rpc.spi;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * SPI获取服务实例Support类
 * @author lichao
 * @date 2020/12/13 11:44
 */
public class ServiceSupport {

    private final static Map<String, Object> singletonServices = new HashMap<>();

    /**
     * SPI加载单个服务接口实例
     * @param serviceClass 服务接口Class
     * @param <S> 服务实例
     * @return 服务实例
     */
    public synchronized static <S> S load(Class<S> serviceClass) {
        return StreamSupport
                .stream(ServiceLoader.load(serviceClass).spliterator(), false)
                .map(ServiceSupport::singletonFilter)
                .findFirst().orElseThrow(ServiceLoadException::new);
    }

    /**
     * SPI加载所有服务接口实例
     * @param serviceClass
     * @param <S> 服务实例
     * @return 服务实例集合
     */
    public synchronized static <S> List<S> loadAll(Class<S> serviceClass) {
        return StreamSupport
                .stream(ServiceLoader.load(serviceClass).spliterator(), false)
                .map(ServiceSupport::singletonFilter)
                .collect(Collectors.toList());
    }

    /**
     * 单例处理
     * @param service
     * @param <S>
     * @return
     */
    private static <S> S singletonFilter(S service) {
        if (service.getClass().isAnnotationPresent(Singleton.class)) {
            String serviceName = service.getClass().getCanonicalName();
            Object singletonObject = singletonServices.putIfAbsent(serviceName, service);
            return singletonObject == null ? service : (S)singletonObject;
        } else {
            return service;
        }
    }
}
